<!DOCTYPE html>
<html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8">
    <title>QBasic快速开发框架 | 说明文档</title>
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <link rel="stylesheet" href="/plugins/bootstrap/css/bootstrap.min.css"/>
    <link rel="stylesheet" href="/css/common.css"/>
    <link rel="stylesheet" href="/css/readme.css"/>
</head>
<body>
<div id="content" class="contentContainer"></div>

<script src="/plugins/markdown/marked.min.js"></script>
<script>
    var rendererMD = new marked.Renderer();
    marked.setOptions({
        renderer: rendererMD,
        gfm: true,
        tables: true,
        breaks: false,
        pedantic: false,
        sanitize: false,
        smartLists: true,
        smartypants: false
    });//基本设置

    //用于个性化输出table
    rendererMD.table = function (header, body) {
        return '<table class="table table-bordered table-striped">'+header+body+'</table>'
    }

    var mdText='# QBasic快速开发框架\n' +
        '### 简介\n' +
        'QBasic快速开发框架，Q是Quick的缩写，QBasic就是快速基础之意。QBasic的开发初衷是为软件部提供一款小而美，轻量而又灵活的项目脚手架。QBasic对目前主流的一些前后端框架做了整合，提供了一个软件项目必须要有的身份验证、权限校验、日志、缓存、全局异常处理、API接口文档等基础功能。来新项目了，开发人员不必再从头开发这些基础功能，直接从业务功能开始开发，减少了大量的重复性工作。\n' +
        '\n' +
        '### 开发原则\n' +
        '- 编码规范\n' +
        '    - 遵循软件部Java开发手册。\n' +
        '- 前后端职责分离\n' +
        '    - 后端代码中没有任何HTML代码，视图层不包含任何后端业务逻辑代码。\n' +
        '    - 前端视图层又做了职责分离，采用MVVM模式，将视图UI和业务逻辑分开。\n' +
        '- 轻量\n' +
        '    - 数据库只有最基础的表和字段。\n' +
        '    - 框架只实现了最基础的功能。\n' +
        '    - 功能页面前端只引用了Vue，jQuery，Element UI框架。\n' +
        '- 代码简洁\n' +
        '    - Controller层没有异常捕获，权限验证，请求参数检验，业务日志代码，统一交给Aop切面处理，Controller层只有业务逻辑代码。\n' +
        '    - 使用Java8新特性lambda表达式，stream流。\n' +
        '- 性能优化\n' +
        '    - 能在应用服务器做的事，不交给数据库做；能在客户端做的事，不交给应用服务器做。\n' +
        '    - 热点数据做缓存，如用户身份信息，权限列表做了缓存。\n' +
        '    - Bootstrap模板AdminLTE的CSS和JS代码做了深度精简，只保留了主页框架页面的部分，加快主页渲染速度。\n' +
        '\n' +
        '### 技术选型\n' +
        '\n' +
        '1、后端\n' +
        '\n' +
        '* Java8：lambda表达式、stream流、optional可空类型等新特性。\n' +
        '* Spring Boot：内嵌式tomcat部署方便；约定大于配置，再不用繁琐的XML配置。\n' +
        '* Spring+Spring MVC+Mybatis：标准的web应用三件套。\n' +
        '* Apache Shiro：安全框架，处理身份认证，授权，会话管理等。\n' +
        '* Thymeleaf：Spring官方推荐的模板引擎。\n' +
        '* Druid：阿里巴巴开源的高性能数据库连接池。\n' +
        '* Ehcache：缓存框架。\n' +
        '* slf4j+logback：日志框架。\n' +
        '* Apache Commons Lang：常用工具包。\n' +
        '* fastJSON：JSON处理工具包。\n' +
        '* Joda-Time：日期处理工具包。\n' +
        '* Swagger：API接口文档自动生成。\n' +
        '\n' +
        '2、前端\n' +
        '\n' +
        '* Vue+jQuery：基础JS框架。\n' +
        '* Element UI：饿了吗前端团队开源的Vue组件库，CSS苦手的福音。\n' +
        '* Bootstrap：UI框架。\n' +
        '* AdminLTE：Bootstrap模板。\n' +
        '* Font Awesome：图标字体。\n' +
        '* CKEditor4：功能强大的富文本编辑器。\n' +
        '* moment：前端日期处理工具包。\n' +
        '\n' +
        '### 后台管理功能概述\n' +
        '\n' +
        '- 用户登录/登出\n' +
        '- 权限校验\n' +
        '    - 用户权限控制到按钮级别\n' +
        '- 系统管理\n' +
        '    - 用户管理\n' +
        '    - 角色管理\n' +
        '    - 资源管理\n' +
        '    - 机构管理\n' +
        '    - 数据字典\n' +
        '    - 系统配置\n' +
        '    - 定时任务\n' +
        '    - 数据集管理\n' +
        '- 运维工具\n' +
        '    - 数据查询\n' +
        '    - 业务日志\n' +
        '    - 错误日志\n' +
        '    - 应用监控\n' +
        '- 内容发布\n' +
        '    - 内容管理\n' +
        '    - 栏目管理\n' +
        '    - 多级审核\n' +
        '    - 全文检索\n' +
        '- 文件存储服务\n' +
        '    - 本地磁盘\n' +
        '    - 阿里云OSS服务    \n' +
        '- 工作流引擎\n' +
        '    - 流程分类\n' +
        '    - 流程定义\n' +
        '    - 流程配置\n' +
        '- 示例代码库\n' +
        '    - 导出Word文档\n' +
        '    - 导出Excel文档\n' +
        '- 全局异常处理\n' +
        '- 全局日志记录\n' +
        '- 缓存\n' +
        '    - 用户身份信息\n' +
        '    - 用户权限信息\n' +
        '- Controller层用户请求、响应参数封装\n' +
        '- 用户请求参数校验\n' +
        '    - 前端、后端请求参数Double Check\n' +
        '- 主页框架页\n' +
        '    - 菜单树\n' +
        '    - 收缩侧边栏\n' +
        '    - 面包屑导航\n' +
        '    - 内容页高度自适应\n' +
        '- 错误页面\n' +
        '    - 400页面\n' +
        '    - 401页面\n' +
        '    - 404页面\n' +
        '    - 500页面\n' +
        '- 检查当前用户会话是否过期\n' +
        '    - 避免出现点击菜单链接内容页嵌套登录页的情况\n' +
        '- 公共HTML模板页\n' +
        '- API接口文档\n' +
        '- 代码生成器，生成单表的增删改查全套代码\n' +
        '\n' +
        '### 接入说明\n' +
        '1. 后台管理站端口8000，管理员账号：admin/123456，测试账号：test/123456\n' +
        '1. 后台管理站接口文档地址/docs，需要先登录\n' +
        '1. 业务日志不需要写数据库的API，请在Controller方法上添加DbLogIgnore注解\n' +
        '1. RESTFUL API接口规范  \n' +
        '\n' +
        '**请求参数示例**   \n' +
        ' ``` \n' +
        ' @ApiModel\n' +
        ' public class EditParamReq extends BaseRequest {\n' +
        ' \n' +
        '     @NotNull(message = "pId不能为空")\n' +
        '     @Min(value = 1, message = "pId必须大于0")\n' +
        '     private Integer pId;\n' +
        ' \n' +
        '     @ApiModelProperty("字典类型")\n' +
        '     @NotEmpty(message = "字典类型不能为空")\n' +
        '     @Length(max = 50, message = "字典类型不能超过50个字符")\n' +
        '     private String pType;\n' +
        ' \n' +
        '     @ApiModelProperty("字典key")\n' +
        '     @NotEmpty(message = "字典key不能为空")\n' +
        '     @Length(max = 50, message = "字典key不能超过50个字符")\n' +
        '     private String pKey;\n' +
        ' \n' +
        '     @ApiModelProperty("字典value")\n' +
        '     @NotEmpty(message = "字典value不能为空")\n' +
        '     @Length(max = 50, message = "字典value不能超过50个字符")\n' +
        '     private String pValue;\n' +
        ' \n' +
        '     @ApiModelProperty("字典排序")\n' +
        '     @NotNull(message = "字典排序不能为空")\n' +
        '     @Range(min = 0, message = "字典排序不能小于0")\n' +
        '     private Integer sort;\n' +
        ' \n' +
        '     @ApiModelProperty("备注")\n' +
        '     private String remark;\n' +
        ' \n' +
        '     public Integer getpId() {\n' +
        '         return pId;\n' +
        '     }\n' +
        ' \n' +
        '     public void setpId(Integer pId) {\n' +
        '         this.pId = pId;\n' +
        '     }\n' +
        ' \n' +
        '     public String getpType() {\n' +
        '         return pType;\n' +
        '     }\n' +
        ' \n' +
        '     public void setpType(String pType) {\n' +
        '         this.pType = pType;\n' +
        '     }\n' +
        ' \n' +
        '     public String getpKey() {\n' +
        '         return pKey;\n' +
        '     }\n' +
        ' \n' +
        '     public void setpKey(String pKey) {\n' +
        '         this.pKey = pKey;\n' +
        '     }\n' +
        ' \n' +
        '     public String getpValue() {\n' +
        '         return pValue;\n' +
        '     }\n' +
        ' \n' +
        '     public void setpValue(String pValue) {\n' +
        '         this.pValue = pValue;\n' +
        '     }\n' +
        ' \n' +
        '     public Integer getSort() {\n' +
        '         return sort;\n' +
        '     }\n' +
        ' \n' +
        '     public void setSort(Integer sort) {\n' +
        '         this.sort = sort;\n' +
        '     }\n' +
        ' \n' +
        '     public String getRemark() {\n' +
        '         return remark;\n' +
        '     }\n' +
        ' \n' +
        '     public void setRemark(String remark) {\n' +
        '         this.remark = remark;\n' +
        '     }\n' +
        ' }\n' +
        ' ```    \n' +
        ' \n' +
        '**返回示例**   \n' +
        '``` \n' +
        '  {\n' +
        '    "status": 200,\n' +
        '    "msg":"成功",\n' +
        '    "result": {\n' +
        '      ...\n' +
        '    }\n' +
        '  }\n' +
        '```\n' +
        '\n' +
        '**返回参数说明**  \n' +
        '\n' +
        '|参数名|类型|说明|\n' +
        '|:-----  |:-----|-----                           |\n' +
        '|status |int   |响应状态码  |\n' +
        '|msg |String   |响应提示信息|\n' +
        '|result |Object   |响应结果  |\n' +
        '\n' +
        '**status响应状态码说明**  \n' +
        '\n' +
        '|状态码|说明|\n' +
        '|:-----  |:-----|\n' +
        '|200 |请求成功|\n' +
        '|400 |接口请求参数不合法，比如手机号不合法|\n' +
        '|401 |身份校验失败  |\n' +
        '|404 |服务器找不到请求的API  |\n' +
        '|500 |系统异常，操作失败，需要客户端做容错处理  |\n' +
        '\n';

    document.getElementById('content').innerHTML = marked(mdText);
</script>
</body>
</html>